--- title: Edge detection subtitle: Edge detection notebook bigimg: /pages/c_03_edge_detection/c_03_bigimg.jpg layout: notebook ---
# to run in google colab
import sys
if 'google.colab' in sys.modules:
! apt-get install subversion
! svn checkout https://github.com/YoniChechik/AI_is_Math/trunk/aux_funcs/
! svn export https://github.com/YoniChechik/AI_is_Math/trunk/c_03_edge_detection/Bikesgray.jpg
! pip install --upgrade bokeh
import numpy as np
import cv2
from matplotlib import pyplot as plt
from aux_funcs import *
fig_size = (10,10)
# to run interactively with vscode
import os
if os.getcwd().endswith("AI_is_Math"):
os.chdir("c_03_edge_detection")
img = cv2.imread("Bikesgray.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.figure(figsize=fig_size)
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.title('Original image')
img = img.astype(float) # 'uint8' doesn't work with minus sign - for filtering
# 1. cv2.filter2D is working with corelation rether than convolution
# no need to flip the kernel
# 2. Notice that kernel is 2D array - if 1d then column vector
kernel = np.array([[-1, 0, +1]])
dst = cv2.filter2D(img, -1, kernel)
plt.figure(figsize=fig_size)
plt.imshow(np.abs(dst), cmap='gray')
plt.colorbar()
plt.title('$f\'_x$: image filtered with '+str(kernel))
Wrong filtering when keeping uint8 instead of float, because uint8 doesn't have negative numbers...
uint8_img = np.zeros((500, 500), dtype=np.uint8)
uint8_img[200:300, 200:300] = 1
kernel = np.array([[-1, 0, +1]])
dst = cv2.filter2D(uint8_img, -1, kernel)
fig, axs = plt.subplots(1, 2, figsize=(20,20))
axs[0].imshow(uint8_img, cmap='gray')
axs[0].title.set_text('original image')
axs[1].imshow(dst, cmap='gray')
axs[1].title.set_text('uint8 WRONG filtering')
kernel = np.array([[-1, 0, +1]]).T
dst = cv2.filter2D(img, -1, kernel)
plt.figure(figsize=fig_size)
plt.imshow(dst, cmap='gray')
plt.colorbar()
plt.title('$f\'_y$: image filtered with\n '+str(kernel))
plt.rcParams['figure.figsize'] = [20, 20]
plt.subplot(4, 2, 1)
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.title('original image')
#######################################
kernel = 1/2*np.array([[-1, 0, +1]])
dst_sym = cv2.filter2D(img, -1, kernel)
plt.subplot(4, 2, 2)
plt.imshow(dst_sym, cmap='gray')
plt.title('$f\'_x$: image filtered with symmetric derivative')
#######################################
kernel = 1/6*np.array([
[-1, 0, +1],
[-1, 0, +1],
[-1, 0, +1]])
dst_prewitt = cv2.filter2D(img, -1, kernel)
plt.subplot(4, 2, 3)
plt.imshow(dst_prewitt, cmap='gray')
plt.title('$f\'_x$: image filtered with Prewitt')
#######################################
# cv2.Sobel() also exist
kernel = 1/8*np.array([
[-1, 0, +1],
[-2, 0, +2],
[-1, 0, +1]])
dst_sobel = cv2.filter2D(img, -1, kernel)
plt.subplot(4, 2, 4)
plt.imshow(dst_sobel, cmap='gray')
plt.title('$f\'_x$: image filtered with Sobel')
#######################################
plt.subplot(4, 2, 5)
plt.imshow(np.abs(dst_sobel-dst_sym))
plt.colorbar()
plt.title('|sobel-symmetric|')
#######################################
plt.subplot(4, 2, 6)
plt.imshow(np.abs(dst_sobel-dst_prewitt))
plt.colorbar()
plt.title('|sobel-prewitt|')
#######################################
plt.subplot(4, 2, 7)
plt.imshow(np.abs(dst_sym-dst_prewitt))
plt.colorbar()
plt.title('|symmetric-prewitt|')
kernel = 1/8*np.array([
[-1, 0, +1],
[-2, 0, +2],
[-1, 0, +1]])
sobel_x = cv2.filter2D(img, -1, kernel)
kernel = kernel.T
sobel_y = cv2.filter2D(img, -1, kernel)
mag_img = np.sqrt(sobel_x**2+sobel_y**2)
phase_img = cv2.phase(sobel_x, -sobel_y, angleInDegrees=True)
phase_img_masked = -100*np.ones(phase_img.shape)
TH_PRC = 0.15
th = mag_img.max()*TH_PRC
phase_img_masked = phase_img_masked*(mag_img <= th) + phase_img*(mag_img > th)
bokeh_imshow(mag_img, scale=1, colorbar=True,
show=True, title='Gradient magnitude')
bokeh_imshow(phase_img_masked, scale=1, colorbar=True,
show=True, title='Gradient phase thresholeded')